package com.Jshop.order.service;

import com.Jshop.common.utils.JsonUtils;
import com.Jshop.order.mapper.OrderDetailMapper;
import com.Jshop.order.mapper.OrderMapper;
import com.Jshop.order.mapper.OrderStatusMapper;
import com.Jshop.order.mapper.SeckillGoodsMapper;
import com.Jshop.order.pojo.*;
import com.leyou.item.pojo.Sku;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenxujun <chenxujun@kuaishou.com>
 * Created on 2021-11-14
 */

@Service
public class SecOrderService {


    @Resource
    private IdWorker idWorker;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderDetailMapper detailMapper;

    @Resource
    private OrderStatusMapper statusMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final Logger logger = LoggerFactory.getLogger(OrderService.class);

    //MQ
    @Resource
    private RabbitTemplate rabbitmq;


    @Resource
    private SeckillGoodsMapper seckillGoodsMapper;

    //create seckill order
    //秒杀订单下单
    public boolean createSecOrder(OrderTransfer message) {


        SeckillGoods good = message.getGood();
        //预检查如果没有库存，则直接抛出异常
        if(good == null || good.getStock() <= 0){
//            throw new RuntimeException("已售罄!");
            logger.info("商品售空!!!");
            return false;
        }

        //直接赋值肯定会导致超卖问题
        //库存减少
        Long stock = this.redisTemplate.boundValueOps("SecKillStockGoodStock_" + good.getId().toString()).increment(1);
        //判断当前商品是否还有库存
        //自增数目超过库存限定数 代表库存耗尽
        if(stock > Long.valueOf(good.getStock())){
            //并且将商品数据同步到MySQL中
            good.setStock(0);
            seckillGoodsMapper.updateByPrimaryKeySelective(good);
            //如果没有库存,则清空Redis缓存中该商品
            redisTemplate.boundHashOps("SeckillGoods_" + message.getTime()).delete(message.getSecKillGoodId().toString());
            //直接抛出异常会导致重复ack 开发体验不好
//            throw new RuntimeException("库存耗尽");
            //更新抢单状态
            SeckillStatus seckillStatus = new SeckillStatus();
            seckillStatus.setStatus(4);
            BoundValueOperations<String, String> killStateRedis = redisTemplate.boundValueOps("SecKill_" + message.getTime() + message.getSecKillGoodId().toString() + "chenxujun_" + "SecKillState");
            killStateRedis.set(JsonUtils.serialize(seckillStatus));
            return false;

        }
        logger.info("当前下单线程: {}", Thread.currentThread().getName());
        //先减掉库存再生成订单
        //生成orderId
        Long orderId = idWorker.nextId();
        //用户抢单状态更新
        SeckillStatus seckillStatus = new SeckillStatus();
        seckillStatus.setStatus(2);
        seckillStatus.setOrderId(orderId);
        BoundValueOperations<String, String> killStateRedis = redisTemplate.boundValueOps("SecKill_" + message.getTime() + message.getSecKillGoodId().toString() + "chenxujun_" + "SecKillState");
        killStateRedis.set(JsonUtils.serialize(seckillStatus));

        //异步 延时消息队列发送
        rabbitmq.convertAndSend("directDelayExchange", "orderDelayQueueKey", (Object)orderId.toString(), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration("30000");
                System.out.println(message + "已发送");
                return message;
            }
        });


        //商品详情
        Sku sku = good.getSku();
        //初始化数据
        Order order = new Order();
        //商品详情
        OrderDetail orderDetail = new OrderDetail();
        BeanUtils.copyProperties(sku, orderDetail);
        ArrayList<OrderDetail> ods = new ArrayList<>();
        ods.add(orderDetail);
        order.setOrderDetails(ods);

        order.setBuyerNick(message.getUserName());
        order.setBuyerRate(false);
        order.setCreateTime(LocalDateTime.now());
        order.setOrderId(orderId);
        order.setUserId(message.getUserId());
        //实付价格
        order.setActualPay(good.getCostPrice());
        // 保存数据
//        this.orderMapper.insertSelective(order);

        // 保存订单状态
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setOrderId(orderId);
        orderStatus.setCreateTime(order.getCreateTime());
        orderStatus.setStatus(1);// 初始状态为未付款
//        this.statusMapper.insertSelective(orderStatus);
        // 订单详情中添加orderId
        order.getOrderDetails().forEach(od -> od.setOrderId(orderId));
        // 保存订单详情,使用批量插入功能
//        this.detailMapper.insertList(order.getOrderDetails());

        SecOrderCache orderCache = new SecOrderCache(order, orderDetail, orderStatus);
        //用户下单，为了提升下单速度，我们将订单数据存入到Redis缓存中
        //如果用户支付了，则将Reids缓存中的订单存入到MySQL中，并清空Redis缓存中的订单
        //所以这里的延时队列应该是独立于普通订单服务的
        System.out.println(message.getUserName());
        redisTemplate.boundHashOps("SeckillOrder_").put(message.getUserName(), JsonUtils.serialize(orderCache));
        String strCacheSecOrder = redisTemplate.boundHashOps("SeckillOrder_").get(message.getUserName()).toString();
        System.out.println("秒杀订单缓存：" + strCacheSecOrder);

        logger.debug("生成订单，订单编号：{}，用户id：{}", orderId, message.getUserName());

        return true;
    }
}
